using System.IO;
using NLog;
using NLog.Config;
using NLog.Layouts;
using NLog.Targets;

namespace NlogTest.NLog
{
    public class NLogConfig
    {
        private static bool _hasInitialized = false;

        /// <summary>
        /// Setup For NLog  
        /// <param>filePrefix<name>FilePrefix Name  </name>   </param>
        /// <param>IsWeb<name>Check for Web service     </name> </param> 
        /// <param>ConnectionString<name>Nlog database table NlogDb Connection String   </name></param>
        /// <param>logpath<name> Absolute path "    </name></param>
        /// </summary>
        public static void InitConFig(string filePrefix, bool isWeb, string connectionString, string logPath)
        {
            if (_hasInitialized) return;

            var obj = new NLogConfig();

            obj.Config(logPath, filePrefix, isWeb, connectionString);

            _hasInitialized = true;
        }

        private void Config(string logPath, string filePrefix, bool isWeb, string connectionString)
        {
            // 1. Create configuration object 
            var config = new LoggingConfiguration();

            #region Logginf config CSV & Database

            var fileTarget = FileTarget(logPath, filePrefix, isWeb);
            config.AddTarget(filePrefix, fileTarget);

            var dbTarget = DataBase(connectionString);
            config.AddTarget("Nlog", dbTarget);
            #endregion

            #region Create Loging Rule
            //for File log level config. maintain log level here
            SimpleConfigurator.ConfigureForTargetLogging(fileTarget, LogLevel.Debug);
            //SimpleConfigurator.ConfigureForTargetLogging(fileTarget, LogLevel.Info);

            //Only for Database log level config. maintain log level here
            SimpleConfigurator.ConfigureForTargetLogging(dbTarget, LogLevel.Debug);
            //SimpleConfigurator.ConfigureForTargetLogging(dbTarget, LogLevel.Info);
            
            var csvruleLog = new LoggingRule("*", LogLevel.Debug, fileTarget);
            config.LoggingRules.Add(csvruleLog);

            var dbruleLog = new LoggingRule("*", LogLevel.Debug, dbTarget);
            config.LoggingRules.Add(dbruleLog);
            #endregion

            // 5. Activate the configuration
            LogManager.Configuration = config;
        }

        #region CSV Logging
        private FileTarget FileTarget(string logPath, string filePrefix, bool isWeb)
        {
            var fileTarget = new FileTarget()
                {
                    //https://github.com/nlog/NLog/wiki/Layout-Renderers

                    FileName = FileName(logPath, filePrefix, isWeb),
                    CreateDirs = true,
                    Layout = CsvLayout(),
                    MaxArchiveFiles = 180,
                    ArchiveEvery = FileArchivePeriod.Month,
                    FileAttributes = (Win32FileAttributes)FileAttributes.ReadOnly,
                    AutoFlush = true,
                    ConcurrentWrites = true,
                    KeepFileOpen = true
                };
            return fileTarget;
        }

        private static string FileName(string logPath, string filePrefix, bool isWeb)
        {
            if (isWeb)
            {
                return logPath + "${aspnet-user-identity}" + filePrefix + "_${date:format = yyyyMMdd}.csv";
            }
            return logPath + filePrefix + "_service_${date:format = yyyyMMdd}.csv";
        }

        // Date:yyyyMMdd Time:HHmmss
        private static CsvLayout CsvLayout()
        {
            var layout = new CsvLayout();
            layout.Columns.Add(new CsvColumn() { Name = "Date", Layout = "${date:format = yyyyMMdd}" });
            layout.Columns.Add(new CsvColumn() { Name = "Time", Layout = "${date:format = HHmmss}" });
            layout.Columns.Add(new CsvColumn() { Name = "Level", Layout = "${level:uppercase=true}" });
            layout.Columns.Add(new CsvColumn() { Name = "Logger", Layout = "${logger}" });
            layout.Columns.Add(new CsvColumn() { Name = "Message", Layout = "${message}" });
            return layout;
        }
        #endregion

        #region Database
        private DatabaseTarget DataBase(string connectionString)
        {
            var database = new DatabaseTarget()
            {
                DBProvider = "MSSQL",
                ConnectionString = connectionString,
                CommandText = @"insert into NlogDb(datetime,level,UserName,logger,message) values(@DateTime, @Level,@UserName, @Logger, @Message);",
                KeepConnection = true
            };

            DbLayouts(database);
            return database;
        }

        private static void DbLayouts(DatabaseTarget database)
        {
            database.Parameters.Add(new DatabaseParameterInfo() { Name = "DateTime", Layout = "${date}" });
            database.Parameters.Add(new DatabaseParameterInfo() { Name = "Level", Layout = "${level:uppercase=true}" });
            database.Parameters.Add(new DatabaseParameterInfo() { Name = "UserName", Layout = "${aspnet-user-identity}" });
            database.Parameters.Add(new DatabaseParameterInfo() { Name = "Logger", Layout = "${logger}" });
            database.Parameters.Add(new DatabaseParameterInfo() { Name = "Message", Layout = "${message}" });
        }
        #endregion
    }
}

#region Console Code
/*
 Nhibernat
 * 
 * NlogDb nlog = new NlogDb
            {
                Level = SimpleLayout.Evaluate("${level:uppercase=true}"),
                UserName = SimpleLayout.Evaluate("${aspnet-user-identity}"),
                DateTime = Convert.ToDateTime(SimpleLayout.Evaluate("${date}").ToString()),
                Logger = SimpleLayout.Evaluate("${logger}"),
                Message = SimpleLayout.Evaluate("${message}"),
            };

            //SessionManager.GetAutomicDao<NlogDb>().SaveOrUpdate(nlog);

            using (var unit = SessionManager.GetCurrentUnitOfWork())
            {
                unit.CurrentSession.SaveOrUpdate(nlog);
                unit.Commit();
            }

 //NlogDb nlog = new NlogDb
            //{
            //    Date = SimpleLayout.Evaluate("${date:format = yyyyMMdd}"),
            //    Time = SimpleLayout.Evaluate("${date:format = HHmmss}"),
            //    Level = SimpleLayout.Evaluate("${level:uppercase=true}"),
            //    Message = SimpleLayout.Evaluate("${message}")
            //};

            //SessionManager.GetAutomicDao<NlogDb>().SaveOrUpdate(nlog);

            //using (var unit = SessionManager.GetCurrentUnitOfWork())
            //{
            //    unit.CurrentSession.SaveOrUpdate(nlog);
            //    unit.Commit();
            //}

 */



//var logger = LogManager.GetCurrentClassLogger();

//logger.Debug("Start Logging");
/*  // 3.Create targets and add them to the configuration 
            var consoleTarget = new ColoredConsoleTarget();
            consoleTarget.Layout = @"${date:format=HH\:MM\:ss} ${logger} ${message}";
            // 4. Define rules for Console
            var rule1 = new LoggingRule("*", LogLevel.Debug, consoleTarget);
               config.LoggingRules.Add(rule1);
            config.AddTarget("console", consoleTarget); */
#endregion